/**
 * @author ahammer
 * @date   2009
 * @update 2010 05 registering tiff or jpeg2000 readers if readers are not available through native imagio  
 */

/*
 * This file is part of Iqm.
 * Copyright (c) 2010-2011 Helmut Ahammer
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package tools;

import java.io.File;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.IIORegistry;
import javax.imageio.stream.ImageInputStream;
import javax.media.jai.PlanarImage;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import main.Board;
import main.Look;

public class ImageHeader {
	//private static int count = 0;
	  
	private static void displayMetadata(Node node, int level) {

	        // print open tag of element
	        indent(level);
	        Board.appendTex("<" + node.getNodeName());
	        NamedNodeMap map = node.getAttributes();
	        if (map != null) {

	            // print attribute values
	        	
	            for (int i = 0; i < map.getLength(); i++) {
	                Node attr = map.item(i);
	                Board.appendTex(" " + attr.getNodeName() + "=\"" + attr.getNodeValue() + "\"");
	            }
	        }

	        Node child = node.getFirstChild();
	        if (child == null) {
	            // no children, so close element and return
	            Board.appendTexln("/>");
	           
	            return;
	        }

	        // children, so close current tag
	        Board.appendTexln(">");
	        int count = 0;
	        while (child != null) {
	            // print children recursively
	            displayMetadata(child, level + 1);
	            child = child.getNextSibling();
	            count = count + 1;
	            if ((level > 2) && (count > 20)){
	            	indent(level);
	            	Board.appendTexln("    .");
	            	indent(level);
	            	Board.appendTexln("    .");
	            	indent(level);
	            	Board.appendTexln("    only first 20 items shown");
	            	indent(level);
	            	Board.appendTexln("    .");
	            	indent(level);
	            	Board.appendTexln("    .");
	            	break;
	            }
	        }

	        // print close tag of element
	        indent(level);
	        Board.appendTexln("</" + node.getNodeName() + ">");
	    }
	    public static  void displayMetadata(Node root) {
	        displayMetadata(root, 0);
	    }

	    private static void indent(int level) {
	        for (int i = 0; i < level; i++)
	            Board.appendTex("    ");
	    }
	    public static  void readAndDisplayMetadata(File file){
	    	

			try {	          
	            ImageInputStream iis = ImageIO.createImageInputStream(file);
	    		if (iis == null){
	    			Board.appendTexln("ImageHeader: No image readers available");
	    			return;
	    		}
	            Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);       
	            if (!readers.hasNext()) { //no reader, perhaps simple imageio without tiff reader installed
		    	   IIORegistry registry = IIORegistry.getDefaultInstance();  
		    	   //registry.registerServiceProvider(new com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriterSpi());  
		    	   if (file.toString().toLowerCase().endsWith("tif") || file.toString().toLowerCase().endsWith("tiff")){
			    	   registry.registerServiceProvider(new com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi()); 
			    	   Board.appendTexln("ImageHeader: additional tiff reader registered");
		    		   
		    	   }
		    	   if (file.toString().toLowerCase().endsWith("jp2") || 
		    		   file.toString().toLowerCase().endsWith("jpc") || 
		    		   file.toString().toLowerCase().endsWith("j2c") || 
		    		   file.toString().toLowerCase().endsWith("j2k") || 
		    		   file.toString().toLowerCase().endsWith("jpx") ){
			    	   registry.registerServiceProvider(new com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderSpi()); 
			    	   Board.appendTexln("ImageHeader: additional jpeg2000 reader registered");	    		   
		    	   }
		    	   readers = ImageIO.getImageReaders(iis);      
	            }
		    		
	            if (readers.hasNext()) {//reader(s) available

	                // pick the first available ImageReader
	                ImageReader reader = readers.next();	    
	           
	                // attach source to the reader
	                reader.setInput(iis, false);  // ImageInputStream,  boolean seekForwardOnly

	                // read metadata of first image
	                //reader.getNumThumbnails(arg0);
	               
	                int numImages = reader.getNumImages(true); //boolean allowSearch (allowSearch == true und seekForwardOnly == true  geht nicht) 
                	Board.appendTexln("ImageHeader: Number of Images: " +numImages);

                	//BoardJ.appendTexln("ImageHeader: File contains more than one image");
                	int firstWidth  = reader.getWidth(0);
                	int firstHeight = reader.getHeight(0);
                	for (int n = 0; n < numImages; n++){
                		int width  = reader.getWidth(n);
                		int height = reader.getHeight(n);
                		float ratioWidth  = (float)firstWidth  / width;
                		float ratioHeight = (float)firstHeight / height;
                		String strNumber       = String.format("%3d", n+1);
                		String strWidth        = String.format("%6d", width);
                		String strHeight       = String.format("%6d", height);
                		String strRatioWidth   = String.format("%5.1f", ratioWidth);
                		String strRatioHeight  = String.format("%5.1f", ratioHeight);
                		Board.appendTexln("Image Number:" + strNumber + "     Width:" + strWidth + "   Height:" + strHeight+ "     Width Ratio:" + strRatioWidth+":1" + "  Height Ratio:" + strRatioHeight+":1" );
                	}
	                int num = 0;
	                if (numImages == 1){ //standard
	                	num = 0;
	                }                	              
	                if (numImages == -1){ //allowSearch is false and a search would be required. 
	                	num = 0;
	                }                	              
	                if (numImages > 1){

	                	//interactive applet
	                	//HeaderImgNumSelection hins = new HeaderImgNumSelection();
	                	//hins.createAndShowGUI();
	                	ImageHeaderNumImgSelection select = new ImageHeaderNumImgSelection(numImages);
	                	num    = select.getSelectedValue()- 1; //selected image number
	                	if (num < 0){ //Abbruch
	                		return;
	                	}
	                }
	                               	
	                IIOMetadata metadata = reader.getImageMetadata(num);
	               
	                //String[] names = metadata.getMetadataFormatNames();   //da kommen gleich mehrere!? z.B. bei jpeg Bild auch tif Metadaten!?        
	                //for (int ii = 0; ii < names.length; ii++) {
	                //    BoardJ.appendTexln( "Format name: " + names[ ii ] );
	                //    ImageHeader.displayMetadata(metadata.getAsTree(names[ii]));
	                //}
		               
	                String fn = metadata.getNativeMetadataFormatName();           
	                Board.appendTexln( "Format name: " + fn );
	                displayMetadata(metadata.getAsTree(fn));
	               
	                reader.dispose();
	            }
	            else {//no readers found
	            	Board.appendTexln("ImageHeader: No image reader found for this image format");
	    	        Board.appendTexln("Perhaps jai-imageio is not installed or the image is defect");
	    	        Board.appendTexln("Following image readers are available:");
	            	printAllAvailableFormatReaders();	            	
	            }
	        }
	        catch (Exception e) {

	            //e.printStackTrace();
	        }

	    }

	
	public static void getCurrImgHeader(){
		PlanarImage pi = Look.getCurrImg();
		if (pi == null){
			Board.appendTexln("ImageHeader: No image and therefore no information");
			return;
		}
		printHeader(pi);
	}
	
	public static void printHeader(PlanarImage pi) {
		if (pi == null){
			Board.appendTexln("ImageHeader: No image and therefore no information");
			return;
		}
		String fileName = (String) pi.getProperty("file_name");
		File file = new File(fileName);
		if (file == null){
			Board.appendTexln("ImageHeader: No file information available");
			return;
		}
		readAndDisplayMetadata(file);
	}
	public static  void printAllAvailableFormatReaders(){
        String[] rfn = ImageIO.getReaderFormatNames();
        for (int n = 0; n < rfn.length; n++){
        	Board.appendTexln("Available reader: " + rfn[n]);
        }
	}
	
}//END